package com.gearbox.core.task;

import com.gearbox.core.driver.AsHandler;
import com.gearbox.core.driver.EcsHandler;
import com.gearbox.core.service.SystemResourceService;
import com.huaweicloud.sdk.as.v1.model.ScalingGroupInstance;
import com.huaweicloud.sdk.ecs.v2.model.ServerAddress;
import com.huaweicloud.sdk.ecs.v2.model.ServerDetail;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
@ConditionalOnProperty(name = "system.type", havingValue = "slurm")
public class RegisterNodeTask {
    private static final Logger LOG = LoggerFactory.getLogger(RegisterNodeTask.class);

    @Autowired
    private AsHandler asHandler;

    @Autowired
    private SystemResourceService systemResourceService;

    @Autowired
    private EcsHandler ecsHandler;

    @Scheduled(initialDelay = 10L, fixedDelayString = "${task.discover-instance-period}", timeUnit = TimeUnit.SECONDS)
    private void doTask() {
        LOG.info("do RegisterNodeTask begin");
        List<ScalingGroupInstance> groupInstances = asHandler.listAllScalingInstance();
        List<ScalingGroupInstance> newInstances = getNewInstances(groupInstances);
        LOG.info("increasedInstance={}", newInstances);
        addInstancesToCluster(newInstances);
        LOG.info("do RegisterNodeTask end");
    }

    List<ScalingGroupInstance> getNewInstances(List<ScalingGroupInstance> groupInstances) {
        return groupInstances.stream()
            .filter(this::isNewInstance)
            .filter(instance -> instance.getLifeCycleState().equals(ScalingGroupInstance.LifeCycleStateEnum.INSERVICE))
            .collect(Collectors.toList());
    }

    boolean isNewInstance(ScalingGroupInstance instance) {
        try {
            return !systemResourceService.isInEtcHosts(instance.getInstanceName().toLowerCase(Locale.ROOT));
        } catch (Exception e) {
            LOG.error("check node:[{}] in /etc/hosts failed", instance.getInstanceName(), e);
            return false;
        }
    }

    void addInstancesToCluster(List<ScalingGroupInstance> newInstances) {
        newInstances.forEach(instance -> addNodeNameAndIpToHosts(instance.getInstanceName().toLowerCase(Locale.ROOT),
            getPrivateIpByInstanceId(instance.getInstanceId())));
    }

    String getPrivateIpByInstanceId(String instanceId) {
        try {
            ServerDetail detail = ecsHandler.getInstanceDetailById(instanceId);
            for (List<ServerAddress> addresses : detail.getAddresses().values()) {
                for (ServerAddress address : addresses) {
                    if (address.getOsEXTIPSType().equals(ServerAddress.OsEXTIPSTypeEnum.FIXED)
                        && address.getAddr() != null && !address.getAddr().isEmpty()) {
                        return address.getAddr();
                    }
                }
            }
            return "";
        } catch (Exception e) {
            LOG.error("get privateIp for instance:[{}] error", instanceId, e);
            return "";
        }

    }

    void addNodeNameAndIpToHosts(String nodeName, String ip) {
        if (nodeName.isEmpty() || ip.isEmpty()) {
            LOG.error("node name or private ip is empty, nodeName:{}, ip:{}", nodeName, ip);
            return;
        }
        try {
            systemResourceService.addEtcHostsRecord(nodeName, ip);
        } catch (Exception e) {
            LOG.error("add instance name and ip to /etc/hosts failed", e);
        }
    }
}
